#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
报告生成器模块
负责根据模板和分析结果生成最终报告
"""

import os
import json
import logging
import re
import html
import datetime
import markdown
from typing import Dict, Any, List, Optional, Union
from pathlib import Path

# 设置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
)
logger = logging.getLogger(__name__)


class ReportGenerationError(Exception):
    """
    报告生成相关异常
    """
    pass


class ReportGenerator:
    """
    报告生成器
    根据分析结果和模板生成最终报告
    """
    
    def __init__(self, template_manager=None):
        """
        初始化报告生成器
        
        Args:
            template_manager: 模板管理器实例，如果为None则自动创建
        """
        # 模板管理器
        if template_manager:
            self._template_manager = template_manager
        else:
            # 动态导入避免循环依赖
            from .report_template_manager import ReportTemplateManager
            self._template_manager = ReportTemplateManager()
        
        logger.info("报告生成器初始化完成")
    
    def _render_template_string(self, template_str: str, context: Dict[str, Any]) -> str:
        """
        渲染单个模板字符串
        使用简单的模板引擎，支持 {{ variable }}、{% for %} 和 {% if %} 语法
        
        Args:
            template_str: 模板字符串
            context: 上下文数据
            
        Returns:
            str: 渲染后的字符串
        """
        try:
            result = template_str
            
            # 处理条件语法 {% if condition %}...{% else %}...{% endif %}
            if_pattern = r'\{%\s*if\s+([\w\._\s=!<>"\']+)\s*%\}\s*(.*?)(?:\s*\{%\s*else\s*%\}\s*(.*?))?\s*\{%\s*endif\s*%\}'
            
            while True:
                match = re.search(if_pattern, result, re.DOTALL)
                if not match:
                    break
                
                condition_expr, true_content, false_content = match.groups()
                
                # 评估条件表达式
                if self._evaluate_condition(condition_expr, context):
                    # 条件为真，渲染true_content
                    rendered_content = self._render_template_string(true_content, context)
                else:
                    # 条件为假，渲染false_content（如果有）
                    if false_content:
                        rendered_content = self._render_template_string(false_content, context)
                    else:
                        rendered_content = ""
                
                # 替换条件块
                result = result[:match.start()] + rendered_content + result[match.end():]
            
            # 处理循环语法 {% for item in items %}...{% endfor %}
            for_loop_pattern = r'\{%\s*for\s+([\w_]+)\s+in\s+([\w_.]+)\s*%\}\s*(.*?)\s*\{%\s*endfor\s*%\}'
            
            while True:
                match = re.search(for_loop_pattern, result, re.DOTALL)
                if not match:
                    break
                
                var_name, collection_path, inner_template = match.groups()
                
                # 获取集合数据
                collection = self._get_nested_value(context, collection_path)
                if not isinstance(collection, (list, tuple, dict)):
                    # 如果不是集合，替换为空
                    result = result[:match.start()] + result[match.end():]
                    continue
                
                # 渲染循环内容
                rendered_content = ""
                if isinstance(collection, dict):
                    # 字典遍历
                    for key, value in collection.items():
                        # 创建循环上下文
                        loop_context = context.copy()
                        loop_context[var_name] = key
                        loop_context["value"] = value
                        loop_context["loop"] = {
                            "index": len(rendered_content.split('\n')) + 1,
                            "first": len(rendered_content) == 0,
                            "last": len(collection) == 1
                        }
                        
                        # 渲染内部模板
                        rendered_content += self._render_template_string(inner_template, loop_context)
                else:
                    # 列表/元组遍历
                    for index, item in enumerate(collection):
                        # 创建循环上下文
                        loop_context = context.copy()
                        loop_context[var_name] = item
                        loop_context["loop"] = {
                            "index": index + 1,
                            "first": index == 0,
                            "last": index == len(collection) - 1
                        }
                        
                        # 渲染内部模板
                        rendered_content += self._render_template_string(inner_template, loop_context)
                
                # 替换循环块
                result = result[:match.start()] + rendered_content + result[match.end():]
            
            # 处理变量替换 {{ variable }} 和 {{ variable.property }} 和 {{ variable | format }}
            var_pattern = r'\{\{\s*([^\{\}|\s]+)\s*((?:\|\s*[\w\.]+(?:\([^\)]*\))?\s*)*)\}\}'
            
            def replace_var(match):
                var_path = match.group(1)
                filters_str = match.group(2).strip()
                
                # 获取变量值
                value = self._get_nested_value(context, var_path)
                
                # 应用过滤器链
                if filters_str:
                    filter_matches = re.finditer(r'\|\s*([\w\.]+)\s*(?:\(([^\)]*)\))?', filters_str)
                    for filter_match in filter_matches:
                        filter_name = filter_match.group(1)
                        filter_args_str = filter_match.group(2) or ''
                        
                        # 解析过滤器参数
                        if filter_args_str:
                            # 处理引号包围的参数
                            args = []
                            # 简单的参数解析，支持逗号分隔
                            raw_args = [arg.strip() for arg in filter_args_str.split(',')]
                            for arg in raw_args:
                                # 移除参数中的引号
                                if (arg.startswith('"') and arg.endswith('"')) or (arg.startswith("'") and arg.endswith("'")):
                                    args.append(arg[1:-1])
                                else:
                                    args.append(arg)
                        else:
                            args = []
                        
                        # 应用过滤器
                        # 根据_apply_filter方法的定义，第三个参数应该是参数字符串或列表
                        value = self._apply_filter(value, filter_name, args)
                
                # 转换为字符串
                if value is None:
                    return ''
                return str(value)
            
            result = re.sub(var_pattern, replace_var, result)
            
            return result
            
        except Exception as e:
            logger.error(f"渲染模板字符串失败: {str(e)}")
            raise ReportGenerationError(f"渲染模板字符串失败: {str(e)}")
    
    def _get_nested_value(self, context: Dict[str, Any], path: str) -> Any:
        """
        获取嵌套值，支持变量引用链和辅助函数调用
        
        Args:
            context: 上下文数据
            path: 变量路径，如 'user.name' 或函数调用表达式
            
        Returns:
            Any: 对应的值
        """
        try:
            # 检查是否包含函数调用
            func_call_match = re.match(r'^([\w\.]+)\(([^)]*)\)$', path)
            if func_call_match:
                func_path = func_call_match.group(1)
                args_str = func_call_match.group(2).strip()
                
                # 获取函数对象
                func_obj = self._get_nested_value(context, func_path)
                if callable(func_obj):
                    # 解析参数
                    args = []
                    if args_str:
                        for arg in args_str.split(','):
                            arg = arg.strip()
                            # 尝试解析参数
                            if arg.startswith('"') and arg.endswith('"') or arg.startswith("'") and arg.endswith("'"):
                                args.append(arg[1:-1])
                            elif arg.isdigit():
                                args.append(int(arg))
                            elif arg.replace('.', '', 1).isdigit() and '.' in arg:
                                args.append(float(arg))
                            elif arg.lower() == 'true':
                                args.append(True)
                            elif arg.lower() == 'false':
                                args.append(False)
                            elif arg.lower() == 'none':
                                args.append(None)
                            else:
                                # 作为变量名处理
                                args.append(self._get_nested_value(context, arg))
                    # 调用函数
                    return func_obj(*args)
                return ''
            
            # 标准路径访问
            parts = path.split('.')
            value = context
            
            # 处理作用域访问
            if parts[0] == '_scopes':
                if len(parts) >= 3:
                    scope_name = parts[1]
                    scope_path = '.'.join(parts[2:])
                    scopes = context.get('_scopes', {})
                    if scope_name in scopes:
                        return self._get_nested_value(scopes[scope_name], scope_path)
                return ''
            
            # 优先在局部作用域查找
            scopes = context.get('_scopes', {})
            if 'local' in scopes and parts[0] in scopes['local']:
                value = scopes['local']
            
            for part in parts:
                if isinstance(value, dict) and part in value:
                    value = value[part]
                else:
                    # 如果在当前作用域找不到，尝试在全局作用域查找
                    if '_scopes' in context and 'global' in context['_scopes']:
                        global_value = self._get_nested_value(context['_scopes']['global'], path)
                        if global_value != '':
                            return global_value
                    return ''
            return value
        except Exception as e:
            logger.error(f"获取嵌套值错误: {path}, 错误: {str(e)}")
            return ''
    
    def _find_max_confidence_category(self, analysis_result: Dict[str, Any]) -> Optional[Dict[str, Any]]:
        """
        查找置信度最高的类别
        
        Args:
            analysis_result: 分析结果数据
            
        Returns:
            Optional[Dict[str, Any]]: 置信度最高的类别数据
        """
        if "category_results" not in analysis_result:
            return None
        
        max_category = None
        max_confidence = -1
        
        for category in analysis_result["category_results"]:
            confidence = category.get("confidence", 0.0)
            if confidence > max_confidence:
                max_confidence = confidence
                max_category = category
        
        return max_category
        
    def _get_top_keywords(self, analysis_result: Dict[str, Any], count: int = 5) -> List[str]:
        """
        获取最重要的关键词
        
        Args:
            analysis_result: 分析结果数据
            count: 返回数量
            
        Returns:
            List[str]: 关键词列表
        """
        keywords = []
        
        if "extracted_keywords" in analysis_result:
            # 按权重排序并取前count个
            sorted_keywords = sorted(analysis_result["extracted_keywords"], 
                                   key=lambda x: x[1] if isinstance(x, tuple) else 0, 
                                   reverse=True)
            keywords = [kw[0] for kw in sorted_keywords[:count]]
        
        return keywords
    
    def _evaluate_condition(self, condition_expr: str, context: Dict[str, Any]) -> bool:
        """
        评估条件表达式
        
        Args:
            condition_expr: 条件表达式字符串
            context: 上下文数据
            
        Returns:
            bool: 条件是否为真
        """
        try:
            # 清理表达式
            condition = condition_expr.strip()
            
            # 处理过滤器在条件中的情况
            if '|' in condition:
                # 查找第一个过滤器位置
                filter_pos = condition.find('|')
                var_part = condition[:filter_pos].strip()
                filter_part = condition[filter_pos:].strip()
                
                # 获取变量值
                var_value = self._get_nested_value(context, var_part)
                
                # 处理过滤器
                filter_name = filter_part[1:].strip().split('(')[0]
                filter_args = []
                if '(' in filter_part:
                    args_match = re.search(r'\(([^)]*)\)', filter_part)
                    if args_match:
                        args_str = args_match.group(1)
                        filter_args = [arg.strip() for arg in args_str.split(',') if arg.strip()]
                
                # 应用过滤器
                result = self._apply_filter(var_value, filter_name, filter_args)
                return bool(result)
            
            # 检查是否是变量存在检查
            if re.match(r'^[\w\.]+$', condition):
                value = self._get_nested_value(context, condition)
                return bool(value)
            
            # 支持简单的比较操作符
            operators = ['==', '!=', '>=', '<=', '>', '<', 'in']
            for op in sorted(operators, key=lambda x: len(x), reverse=True):
                if op in condition:
                    parts = condition.split(op, 1)
                    if len(parts) != 2:
                        continue
                    
                    left = parts[0].strip()
                    right = parts[1].strip()
                    
                    # 处理左侧可能包含的过滤器
                    left_value = None
                    if '|' in left:
                        filter_pos = left.find('|')
                        left_var = left[:filter_pos].strip()
                        left_filter = left[filter_pos:].strip()
                        
                        left_var_value = self._get_nested_value(context, left_var)
                        
                        filter_name = left_filter[1:].strip().split('(')[0]
                        filter_args = []
                        if '(' in left_filter:
                            args_match = re.search(r'\(([^)]*)\)', left_filter)
                            if args_match:
                                args_str = args_match.group(1)
                                filter_args = [arg.strip() for arg in args_str.split(',') if arg.strip()]
                        
                        left_value = self._apply_filter(left_var_value, filter_name, filter_args)
                    else:
                        # 常规方式解析左边的值
                        if re.match(r'^[\w\.]+$', left):
                            left_value = self._get_nested_value(context, left)
                        else:
                            left_value = self._parse_literal(left)
                    
                    # 处理右侧可能包含的过滤器
                    right_value = None
                    if '|' in right and op != 'in':
                        filter_pos = right.find('|')
                        right_var = right[:filter_pos].strip()
                        right_filter = right[filter_pos:].strip()
                        
                        right_var_value = self._get_nested_value(context, right_var)
                        
                        filter_name = right_filter[1:].strip().split('(')[0]
                        filter_args = []
                        if '(' in right_filter:
                            args_match = re.search(r'\(([^)]*)\)', right_filter)
                            if args_match:
                                args_str = args_match.group(1)
                                filter_args = [arg.strip() for arg in args_str.split(',') if arg.strip()]
                        
                        right_value = self._apply_filter(right_var_value, filter_name, filter_args)
                    else:
                        # 常规方式解析右边的值
                        if re.match(r'^[\w\.]+$', right) and op != 'in':
                            right_value = self._get_nested_value(context, right)
                        else:
                            right_value = self._parse_literal(right)
                    
                    # 执行比较
                    try:
                        if op == '==':
                            return left_value == right_value
                        elif op == '!=':
                            return left_value != right_value
                        elif op == '>=':
                            return left_value >= right_value
                        elif op == '<=':
                            return left_value <= right_value
                        elif op == '>':
                            return left_value > right_value
                        elif op == '<':
                            return left_value < right_value
                        elif op == 'in':
                            return left_value in right_value
                    except (TypeError, ValueError):
                        # 比较失败时进行类型转换后再比较
                        try:
                            return str(left_value) > str(right_value) if op == '>' else str(left_value) < str(right_value)
                        except:
                            return False
            
            # 检查布尔值字面量
            if condition.lower() == 'true':
                return True
            elif condition.lower() == 'false':
                return False
            
            # 如果无法解析，默认返回False
            return False
            
        except Exception as e:
            # 评估错误时返回False
            logger.error(f"条件表达式评估错误: {condition_expr}, 错误: {str(e)}")
            return False
    
    def _parse_literal(self, value_str: str) -> Any:
        """
        解析字面值
        
        Args:
            value_str: 字符串形式的值
            
        Returns:
            Any: 解析后的值
        """
        try:
            # 处理字符串
            if (value_str.startswith('"') and value_str.endswith('"')) or \
               (value_str.startswith("'") and value_str.endswith("'")):
                return value_str[1:-1]
            
            # 处理数字
            if value_str.isdigit():
                return int(value_str)
            
            # 处理浮点数
            try:
                return float(value_str)
            except ValueError:
                pass
            
            # 处理布尔值
            if value_str.lower() == 'true':
                return True
            if value_str.lower() == 'false':
                return False
            
            # 处理None
            if value_str.lower() == 'none':
                return None
            
            # 返回原始字符串
            return value_str
            
        except Exception:
            return value_str
    
    def _apply_filter(self, value: Any, filter_name: str, args_str_or_list: Union[str, List[str]] = None) -> Any:
        """
        应用过滤器到值
        
        Args:
            value: 要过滤的值
            filter_name: 过滤器名称
            args_str_or_list: 过滤器参数字符串或列表
            
        Returns:
            Any: 过滤后的值
        """
        try:
            # 解析参数（无论是否有参数都执行）
            args = []
            if args_str_or_list:
                if isinstance(args_str_or_list, list):
                    args = args_str_or_list
                else:
                    args = [arg.strip() for arg in args_str_or_list.split(',')]
            
            # 无条件处理所有过滤器
            if filter_name == 'upper':
                return str(value).upper() if value is not None else ''
            elif filter_name == 'lower':
                return str(value).lower() if value is not None else ''
            elif filter_name == 'title':
                # 将每个单词首字母大写
                s = str(value) if value is not None else ''
                return ' '.join(word.capitalize() for word in s.split())
            elif filter_name == 'capitalize':
                # 将字符串首字母大写，其余小写
                return str(value).capitalize() if value is not None else ''
            elif filter_name == 'strip':
                return str(value).strip() if value is not None else ''
            elif filter_name == 'len' or filter_name == 'length':
                # 支持len和length两种名称
                return len(value) if value is not None else 0
            elif filter_name == 'round':
                # 四舍五入，支持指定小数位数
                try:
                    decimals = int(args[0]) if args else 0
                    return round(float(value), decimals) if value is not None else 0
                except (ValueError, TypeError):
                    return str(value) if value is not None else ''
            elif filter_name == 'format':
                # 格式字符串
                if args:
                    # 使用解析后的第一个参数作为格式字符串
                    format_str = args[0].strip('"\'')
                    try:
                        # 处理数字格式化
                        if isinstance(value, (int, float)):
                            if '万' in format_str:
                                # 处理万为单位的格式化
                                return format_str % (value / 10000)
                            return format_str % value
                        return format_str % value
                    except (ValueError, TypeError):
                        return str(value) if value is not None else ''
                return str(value) if value is not None else ''
            elif filter_name == 'join':
                # 连接列表元素
                if isinstance(value, (list, tuple)):
                    separator = args[0] if args else ', '
                    try:
                        return separator.join([str(item) for item in value])
                    except (TypeError, AttributeError):
                        return str(value) if value is not None else ''
                return str(value) if value is not None else ''
            elif filter_name == 'date':
                # 日期格式化
                if isinstance(value, (datetime.datetime, datetime.date)):
                    format_str = args[0] if args else '%Y-%m-%d %H:%M:%S'
                    return value.strftime(format_str)
                return str(value) if value is not None else ''
            elif filter_name == 'first':
                # 获取第一个元素
                if isinstance(value, (list, tuple)) and value:
                    return value[0]
                elif isinstance(value, str) and value:
                    return value[0]
                return ''
            elif filter_name == 'last':
                # 获取最后一个元素
                if isinstance(value, (list, tuple)) and value:
                    return value[-1]
                elif isinstance(value, str) and value:
                    return value[-1]
                return ''
            elif filter_name == 'default' and args:
                # 默认值过滤器
                if value is None or value == '':
                    return args[0]
                return value
            elif filter_name == 'replace' and len(args) >= 2:
                # 替换字符串
                return str(value).replace(args[0], args[1]) if value is not None else ''
            elif filter_name == 'slice' and args:
                # 切片操作
                if isinstance(value, (str, list, tuple)):
                    try:
                        start = int(args[0]) if args[0] else 0
                        end = int(args[1]) if len(args) > 1 and args[1] else len(value)
                        return value[start:end]
                    except (ValueError, TypeError, IndexError):
                        pass
                return value
            elif filter_name == 'round' and args:
                # 四舍五入
                try:
                    decimal_places = int(args[0]) if args[0] else 0
                    return round(float(value), decimal_places)
                except (ValueError, TypeError):
                    return value
            elif filter_name == 'int':
                # 转换为整数
                try:
                    return int(float(value))
                except (ValueError, TypeError):
                    return 0
            elif filter_name == 'float':
                # 转换为浮点数
                try:
                    return float(value)
                except (ValueError, TypeError):
                    return 0.0
            elif filter_name == 'capitalize':
                # 首字母大写，支持中英文混合处理
                s = str(value) if value is not None else ''
                if s:
                    # 对于中文，保持原样；对于英文，首字母大写
                    if s[0].encode('utf-8', errors='ignore').isalpha():
                        return s[0].upper() + s[1:].lower()
                return s
            elif filter_name == 'escape':
                # 转义HTML特殊字符
                import html
                return html.escape(str(value)) if value is not None else ''
            elif filter_name == 'duration_format':
                # 将秒数转换为时:分:秒格式
                try:
                    seconds = float(value)
                    hours = int(seconds // 3600)
                    minutes = int((seconds % 3600) // 60)
                    secs = int(seconds % 60)
                    if hours > 0:
                        return f"{hours}:{minutes:02d}:{secs:02d}"
                    else:
                        return f"{minutes}:{secs:02d}"
                except (ValueError, TypeError):
                    return str(value) if value is not None else ''
            
            # 默认返回原值
            return value
            
        except Exception as e:
            logger.error(f"应用过滤器失败: {filter_name}, {str(e)}")
            return value
    
    def generate_report(self, 
                       analysis_result: Dict[str, Any],
                       template_name: str = None,
                       output_format: str = "markdown",
                       custom_variables: Dict[str, Any] = None) -> str:
        """
        生成报告，支持自定义变量
        
        Args:
            analysis_result: 分析结果数据
            template_name: 模板名称
            output_format: 输出格式
            custom_variables: 自定义变量字典，可在模板中使用
            
        Returns:
            str: 生成的报告内容
        """
        try:
            # 获取模板
            template = self._template_manager.get_template(template_name)
            
            # 检查输出格式是否支持
            supported_formats = template.get("output_formats", ["markdown", "txt"])
            if output_format.lower() not in supported_formats:
                logger.warning(f"模板不支持 {output_format} 格式，使用默认格式 {supported_formats[0]}")
                output_format = supported_formats[0]
            
            # 准备上下文数据，传入自定义变量
            context = self._prepare_context(analysis_result, custom_variables)
            
            # 渲染每个章节
            report_content = ""
            for section in template.get("sections", []):
                section_content = self._render_template_string(section.get("content", ""), context)
                report_content += section_content
            
            # 根据输出格式进行后处理
            final_content = self._post_process_content(report_content, output_format)
            
            logger.info(f"报告生成成功，格式: {output_format}")
            return final_content
            
        except Exception as e:
            logger.error(f"生成报告失败: {str(e)}")
            raise ReportGenerationError(f"生成报告失败: {str(e)}")
    
    def _prepare_context(self, analysis_result: Dict[str, Any], custom_variables: Dict[str, Any] = None) -> Dict[str, Any]:
        """
        准备渲染上下文，支持变量作用域和自定义变量
        
        Args:
            analysis_result: 分析结果数据
            custom_variables: 自定义变量字典，可在模板中使用
            
        Returns:
            Dict[str, Any]: 渲染上下文
        """
        # 创建作用域结构
        scopes = {
            "global": {},  # 全局作用域
            "local": {},   # 局部作用域（循环等块内使用）
            "custom": {}   # 自定义变量作用域
        }
        
        # 基础上下文数据
        base_context = {
            "report_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "analysis_tool": "AI大模型视频编码分析系统",
            "video_id": analysis_result.get("video_id", "未知"),
            "video_title": analysis_result.get("video_title", ""),
            # 处理热门评论
            "hot_comment": "暂无评论"
        }
        
        # 尝试获取热门评论
        comments = analysis_result.get('comments', [])
        hot_comments = analysis_result.get('hot_comments', [])
        if hot_comments and isinstance(hot_comments, list) and hot_comments:
            base_context['hot_comment'] = hot_comments[0].get('content', '') if isinstance(hot_comments[0], dict) else str(hot_comments[0])
        elif comments and isinstance(comments, list) and comments:
            # 如果没有热门评论但有普通评论，使用第一条普通评论
            base_context['hot_comment'] = comments[0].get('content', '') if isinstance(comments[0], dict) else str(comments[0])
        
        # 编码类目分析结果
        category_analysis = {}
        if "category_results" in analysis_result:
            for category_data in analysis_result["category_results"]:
                category_name = category_data.get("category_name", "")
                if category_name:
                    category_analysis[category_name] = {
                        "result": category_data.get("result", "未知"),
                        "confidence": category_data.get("confidence", 0.0),
                        "reasoning": category_data.get("reasoning", ""),
                        "keywords": category_data.get("keywords", [])
                    }
        base_context["category_analysis"] = category_analysis
        
        # 整体摘要
        base_context["overall_summary"] = analysis_result.get("overall_summary", "")
        
        # 视觉特征
        visual_features = {
            "scene_description": analysis_result.get("scene_description", ""),
            "key_elements": analysis_result.get("key_elements", []),
            "colors": analysis_result.get("main_colors", []),
            "images_count": analysis_result.get("total_frames", 0),
            "valid_frames_count": analysis_result.get("analyzed_frames", 0)
        }
        base_context["visual_features"] = visual_features
        
        # 文本特征
        text_features = {
            "sentiment": analysis_result.get("sentiment_analysis", {}),
            "keywords": analysis_result.get("extracted_keywords", []),
            "topics": analysis_result.get("topic_analysis", []),
            "summary": analysis_result.get("text_summary", "")
        }
        base_context["text_features"] = text_features
        
        # 总结与建议
        base_context["content_summary"] = analysis_result.get("content_summary", "")
        base_context["audience_suggestions"] = analysis_result.get("audience_suggestions", "")
        base_context["optimization_suggestions"] = analysis_result.get("optimization_suggestions", "")
        
        # 设置全局作用域
        scopes["global"].update(base_context)
        scopes["global"]["analysis_result"] = analysis_result
        
        # 添加派生变量和辅助函数
        self._add_derived_variables(scopes["global"], analysis_result)
        
        # 添加自定义变量
        if custom_variables:
            scopes["custom"].update(custom_variables)
        
        # 构建最终上下文，同时保留原始变量以便直接访问
        context = {}
        context.update(scopes["global"])
        context.update(scopes["custom"])
        context["_scopes"] = scopes  # 保存作用域结构，供渲染时使用
        
        return context
        
    def _add_derived_variables(self, global_scope: Dict[str, Any], analysis_result: Dict[str, Any]):
        """
        添加派生变量和辅助函数到全局作用域
        
        Args:
            global_scope: 全局作用域字典
            analysis_result: 分析结果数据
        """
        # 常用派生变量
        global_scope["has_categories"] = "category_results" in analysis_result and len(analysis_result["category_results"]) > 0
        global_scope["has_key_elements"] = "key_elements" in analysis_result and len(analysis_result["key_elements"]) > 0
        
        # 提取所有肯定结果的类目
        positive_categories = []
        if "category_results" in analysis_result:
            positive_categories = [
                cat for cat in analysis_result["category_results"] 
                if cat.get("result", "").lower() == "是"
            ]
        global_scope["positive_categories"] = positive_categories
        global_scope["has_positive_categories"] = len(positive_categories) > 0
        
        # 提取所有关键词（合并所有来源）
        all_keywords = []
        if "extracted_keywords" in analysis_result:
            all_keywords.extend([kw[0] for kw in analysis_result["extracted_keywords"]])
        
        if "category_results" in analysis_result:
            for cat in analysis_result["category_results"]:
                if "keywords" in cat:
                    all_keywords.extend(cat["keywords"])
        
        # 去重并保持顺序
        seen = set()
        unique_keywords = [x for x in all_keywords if not (x in seen or seen.add(x))]
        global_scope["all_keywords"] = unique_keywords
        global_scope["keyword_count"] = len(unique_keywords)
        
        # 添加辅助函数引用（通过变量引用链使用）
        global_scope["_helpers"] = {
            "max_confidence_category": lambda: self._find_max_confidence_category(analysis_result),
            "top_keywords": lambda n=5: self._get_top_keywords(analysis_result, n),
            "format_percent": lambda value: f"{value:.1%}",
        }
    
    def _post_process_content(self, content: str, output_format: str) -> str:
        """
        后处理报告内容
        
        Args:
            content: 报告内容
            output_format: 输出格式
            
        Returns:
            str: 处理后的内容
        """
        output_format = output_format.lower()
        
        if output_format == "html":
            # HTML 格式已经在模板中处理
            return content
        elif output_format == "markdown":
            # Markdown 格式不需要特别处理
            return content.strip()
        elif output_format == "txt":
            # 纯文本格式，移除Markdown标记
            # 移除标题标记
            content = re.sub(r'^#{1,6}\s+', '', content, flags=re.MULTILINE)
            # 移除粗体标记
            content = re.sub(r'\*\*(.+?)\*\*', r'\1', content)
            # 移除斜体标记
            content = re.sub(r'\*(.+?)\*', r'\1', content)
            # 移除链接标记
            content = re.sub(r'\[([^\]]+)\]\([^\)]+\)', r'\1', content)
            # 移除代码块标记
            content = re.sub(r'```[\w]*\n([\s\S]*?)```', r'\1', content)
            # 移除行内代码标记
            content = re.sub(r'`([^`]+)`', r'\1', content)
            # 移除表格标记（简化处理）
            content = re.sub(r'\|\s*', '', content)
            content = re.sub(r'^-+$', '', content, flags=re.MULTILINE)
            # 清理多余的空行
            content = re.sub(r'\n\s*\n\s*\n', '\n\n', content)
            return content.strip()
        else:
            # 默认返回原始内容
            return content.strip()
    
    def markdown_to_html(self, markdown_content: str) -> str:
        """
        将Markdown转换为HTML
        
        Args:
            markdown_content: Markdown内容
            
        Returns:
            str: HTML内容
        """
        try:
            # 添加基本的HTML头部和样式
            html_header = '''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>视频分析报告</title>
    <style>
        body { font-family: Arial, 'Microsoft YaHei', sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #2c3e50; }
        h1 { border-bottom: 2px solid #3498db; padding-bottom: 10px; }
        h2 { border-bottom: 1px solid #ecf0f1; padding-bottom: 5px; }
        table { border-collapse: collapse; width: 100%; margin: 20px 0; }
        th, td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; }
        th { background-color: #f2f2f2; }
        tr:nth-child(even) { background-color: #f9f9f9; }
        blockquote { border-left: 4px solid #3498db; margin: 15px 0; padding: 10px 20px; background-color: #f9f9f9; }
        code { background-color: #f1f1f1; padding: 2px 4px; border-radius: 3px; }
        pre { background-color: #f5f5f5; padding: 15px; border-radius: 5px; overflow-x: auto; }
    </style>
</head>
<body>
'''
            
            html_footer = '''
</body>
</html>'''
            
            # 转换Markdown
            html_content = markdown.markdown(
                markdown_content,
                extensions=[
                    'fenced_code',
                    'codehilite',
                    'tables',
                    'toc'
                ]
            )
            
            # 组合完整的HTML
            full_html = html_header + html_content + html_footer
            
            return full_html
            
        except Exception as e:
            logger.error(f"Markdown转HTML失败: {str(e)}")
            raise ReportGenerationError(f"Markdown转HTML失败: {str(e)}")
    
    def save_report(self, 
                   report_content: str,
                   output_path: str,
                   output_format: str = "markdown") -> bool:
        """
        保存报告到文件
        
        Args:
            report_content: 报告内容
            output_path: 输出路径
            output_format: 输出格式
            
        Returns:
            bool: 是否保存成功
        """
        try:
            # 确保目录存在
            os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
            
            # 确定文件扩展名
            ext = os.path.splitext(output_path)[1].lower()
            if not ext:
                # 根据格式添加扩展名
                ext_map = {
                    "markdown": ".md",
                    "html": ".html",
                    "txt": ".txt"
                }
                output_path += ext_map.get(output_format.lower(), ".md")
            
            # 保存文件
            with open(output_path, 'w', encoding='utf-8') as f:
                f.write(report_content)
            
            logger.info(f"报告保存成功: {output_path}")
            return True
            
        except Exception as e:
            logger.error(f"保存报告失败: {str(e)}")
            raise ReportGenerationError(f"保存报告失败: {str(e)}")
    
    def generate_and_save_report(self, 
                                analysis_result: Dict[str, Any],
                                output_path: str,
                                template_name: str = None,
                                output_format: str = "markdown") -> str:
        """
        生成并保存报告
        
        Args:
            analysis_result: 分析结果数据
            output_path: 输出路径
            template_name: 模板名称
            output_format: 输出格式
            
        Returns:
            str: 保存的文件路径
        """
        try:
            # 生成报告
            report_content = self.generate_report(analysis_result, template_name, output_format)
            
            # 保存报告
            self.save_report(report_content, output_path, output_format)
            
            return output_path
            
        except Exception as e:
            logger.error(f"生成并保存报告失败: {str(e)}")
            raise ReportGenerationError(f"生成并保存报告失败: {str(e)}")
    
    def create_summary_report(self, 
                             analysis_result: Dict[str, Any],
                             output_format: str = "markdown") -> str:
        """
        创建摘要报告（使用简洁模板）
        
        Args:
            analysis_result: 分析结果数据
            output_format: 输出格式
            
        Returns:
            str: 报告内容
        """
        return self.generate_report(analysis_result, "concise", output_format)
    
    def create_detailed_report(self, 
                              analysis_result: Dict[str, Any],
                              output_format: str = "markdown") -> str:
        """
        创建详细报告（使用标准模板）
        
        Args:
            analysis_result: 分析结果数据
            output_format: 输出格式
            
        Returns:
            str: 报告内容
        """
        return self.generate_report(analysis_result, "standard", output_format)
    
    def create_html_report(self, analysis_result: Dict[str, Any]) -> str:
        """
        创建HTML格式报告
        
        Args:
            analysis_result: 分析结果数据
            
        Returns:
            str: HTML报告内容
        """
        return self.generate_report(analysis_result, "html", "html")
    
    def validate_report_data(self, analysis_result: Dict[str, Any]) -> Dict[str, Any]:
        """
        验证报告数据格式
        
        Args:
            analysis_result: 分析结果数据
            
        Returns:
            Dict[str, Any]: 验证结果 {"valid": bool, "warnings": []}
        """
        warnings = []
        
        # 检查必要字段
        required_fields = ["video_id", "category_results"]
        for field in required_fields:
            if field not in analysis_result:
                warnings.append(f"缺少必要字段: {field}")
        
        # 检查category_results格式
        if "category_results" in analysis_result:
            if not isinstance(analysis_result["category_results"], list):
                warnings.append("category_results必须是列表类型")
            else:
                for idx, category in enumerate(analysis_result["category_results"]):
                    if "category_name" not in category:
                        warnings.append(f"第{idx+1}个类目缺少category_name字段")
                    if "result" not in category:
                        warnings.append(f"第{idx+1}个类目缺少result字段")
                    if "confidence" not in category:
                        warnings.append(f"第{idx+1}个类目缺少confidence字段")
        
        return {
            "valid": len(warnings) == 0,
            "warnings": warnings
        }


# 使用示例
if __name__ == '__main__':
    try:
        print("报告生成器测试中...")
        
        # 创建测试数据
        test_analysis_result = {
            "video_id": "test_video_001",
            "video_title": "测试视频",
            "overall_summary": "这是一个测试视频，内容丰富多样。",
            "category_results": [
                {
                    "category_name": "生活方式",
                    "result": "是",
                    "confidence": 0.95,
                    "reasoning": "视频中包含大量日常生活场景",
                    "keywords": ["日常", "生活", "场景"]
                },
                {
                    "category_name": "教育",
                    "result": "否",
                    "confidence": 0.87,
                    "reasoning": "未发现明显的教育内容",
                    "keywords": []
                },
                {
                    "category_name": "娱乐",
                    "result": "是",
                    "confidence": 0.75,
                    "reasoning": "视频包含娱乐元素",
                    "keywords": ["娱乐", "休闲"]
                }
            ],
            "scene_description": "室内生活场景",
            "key_elements": [
                {"name": "沙发", "confidence": 0.92},
                {"name": "电视", "confidence": 0.88},
                {"name": "茶几", "confidence": 0.76}
            ],
            "main_colors": ["蓝色", "白色", "灰色"],
            "total_frames": 5,
            "analyzed_frames": 5,
            "sentiment_analysis": {
                "label": "积极",
                "confidence": 0.85
            },
            "extracted_keywords": [
                ("生活", 0.95),
                ("日常", 0.88),
                ("测试", 0.82),
                ("视频", 0.78),
                ("场景", 0.72)
            ],
            "topic_analysis": [
                {
                    "topic": "家居生活",
                    "keywords": ["沙发", "电视", "茶几"],
                    "relevance": 0.92
                }
            ],
            "text_summary": "这是一个展示家居生活场景的测试视频。",
            "content_summary": "视频主要展示了家居生活场景，内容积极向上。",
            "audience_suggestions": "适合普通家庭观众观看。",
            "optimization_suggestions": "建议增加更多互动元素。"
        }
        
        # 创建生成器
        generator = ReportGenerator()
        
        # 验证数据
        validation_result = generator.validate_report_data(test_analysis_result)
        print(f"\n数据验证结果: {'有效' if validation_result['valid'] else '有警告'}")
        if validation_result['warnings']:
            for warning in validation_result['warnings']:
                print(f"  - {warning}")
        
        # 生成简洁报告
        concise_report = generator.create_summary_report(test_analysis_result)
        print("\n简洁报告生成成功!")
        
        # 生成详细报告
        detailed_report = generator.create_detailed_report(test_analysis_result)
        print("详细报告生成成功!")
        
        # 生成HTML报告
        html_report = generator.create_html_report(test_analysis_result)
        print("HTML报告生成成功!")
        
        # 保存报告到临时目录
        output_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "output")
        
        # 保存简洁报告
        concise_path = os.path.join(output_dir, "test_concise_report")
        generator.save_report(concise_report, concise_path, "markdown")
        print(f"简洁报告已保存: {concise_path}.md")
        
        # 保存详细报告
        detailed_path = os.path.join(output_dir, "test_detailed_report")
        generator.save_report(detailed_report, detailed_path, "markdown")
        print(f"详细报告已保存: {detailed_path}.md")
        
        # 保存HTML报告
        html_path = os.path.join(output_dir, "test_html_report.html")
        generator.save_report(html_report, html_path, "html")
        print(f"HTML报告已保存: {html_path}")
        
        print("\n报告生成器测试完成!")
        
    except Exception as e:
        print(f"测试失败: {str(e)}")